#!/bin/bash

# Patchwork - automated patch tracking system
# Copyright (C) 2010 martin f. krafft <madduck@madduck.net>
#
# SPDX-License-Identifier: GPL-2.0-or-later

# Git post-receive hook to update Patchwork patches after Git pushes
set -eu

PW_DIR=/opt/patchwork/patchwork

#TODO: the state map should really live in the repo's git-config
STATE_MAP="refs/heads/master:Accepted"

# ignore all commits already present in these refs
# e.g.,
#   EXCLUDE="refs/heads/upstream refs/heads/other-project"
EXCLUDE=""

do_exit=0
trap "do_exit=1" INT

get_patchwork_hash() {
    local hash
    hash=$(git diff "$1~..$1" | python $PW_DIR/hasher.py)
    echo "$hash"
    test -n "$hash"
}

get_patch_id() {
    local id
    id=$(pwclient info -h "$1" 2>/dev/null | \
         sed -rne 's,- id[[:space:]]*: ,,p')
    echo "$id"
    test -n "$id"
}

set_patch_state() {
    pwclient update -s "$2" -c "$3" "$1" 2>&1
}

update_patches() {
    local cnt; cnt=0
    for rev in $(git rev-parse --not ${EXCLUDE} |
                 git rev-list --stdin --no-merges --reverse "${1}".."${2}"); do
        if [ "$do_exit" = 1 ]; then
            echo "I: exiting..." >&2
            break
        fi
        hash=$(get_patchwork_hash "$rev")
        if [ -z "$hash" ]; then
            echo "E: failed to hash rev $rev." >&2
            continue
        fi
        id=$(get_patch_id "$hash" || true)
        if [ -z "$id" ]; then
            echo "E: failed to find patch for rev $rev." >&2
            continue
        fi
        reason="$(set_patch_state "$id" "$3" "$rev")"
        if [ -n "$reason" ]; then
            echo "E: failed to update patch #$id${reason:+: $reason}." >&2
            continue
        fi
        echo "I: patch #$id updated using rev $rev." >&2
        cnt=$((cnt + 1))
    done

    echo "I: $cnt patch(es) updated to state $3." >&2
}

while read -r oldrev newrev refname; do
    found=0
    for i in $STATE_MAP; do
        key="${i%:*}"
        if [ "$key" = "$refname" ]; then
            update_patches "$oldrev" "$newrev" ${i#*:}
            found=1
            break
        fi
    done
    if [ $found -eq 0 ]; then
        echo "E: STATE_MAP has no mapping for branch $refname" >&2
    fi
done
